/*
 * Layer.h
 *
 *  Created on: 04/01/2012
 *      Author: luiz
 */

#ifndef LAYER_H_
#define LAYER_H_

#include <string>
#include <vector>
#include <set>
#include "Cell.h"


class Layer {
private:

    // store matrix off cell
    Cell ***layer_grid;

    // number of horizontal cell's on grid
    int grid_size_x_;

    // number of vertical cell's on grid
    int grid_size_y_;

    std::vector<Cell*> cell_list_;

    int number_of_positions_used_per_cell_;

    //initialize and allocate properties
    void initialize();

    //deallocate and free all properties
    void deinitilize();


public:

    /*
     * Constructor
     */
    Layer(int grid_size_horizonta=0,int grid_size_vertica=0,int number_of_positions_used_per_cell=0);


    Layer(const Layer &layer);

    Layer& operator=(const Layer & layer);

    virtual ~Layer();


    /*
     * Methods
     */

    // create new cell at position on layer (grid) (x  and y axis)
    // @param int position x, int position y
    // @return Cell pointer to created cell - NULL if this cell wasn't created
    Cell* create_new_cell_at(int position_x,int position_y);

    void remove_cell_at(int position_x,int position_y);

    void remove_cell(Cell* cell);

    int number_of_cells() const;

    Cell* get_cell_at_list_index(int cell_index);

    Cell* get_cell_by_id(int id);

    Cell* get_cell_at_position(int pos_x, int pos_y);

    int number_of_cells_by_function(Cell::CELL_FUNCTION function);

    int number_of_positions_used_per_cell();

    void set_number_of_positions_used_per_cell(int number_of_positions_used_per_cell);

    int get_output_shift();

    bool verify_insertion(int pos_x, int pos_y);

    bool verify_conex();

    bool verify_conex_before_remove(Cell *cell);

    int grid_size_x() const;

    int grid_size_y() const;

    std::vector<Cell*> get_list_cells_by_function(Layer *layer,Cell::CELL_FUNCTION cell_function);

    std::vector<Cell*> cell_list() const;

    std::set<std::pair<int,int> > get_list_empty_places();

    std::vector<std::pair<int,int> > get_empty_neighborhood(Cell * cell, Layer * layer);

    Cell* get_lower_clock_zone_cell_neighborhood(Cell * cell, Layer * layer);

    int get_number_of_cells() const;

    void sort_cells();

    // return string with layer information
    // @return string
    std::string print_layer();

    std::string print_cell_list() const;

    bool compare_cell_list_less_than(const std::vector<Cell *> &cell_list_a, const std::vector<Cell *> & cell_list_b) const;
    bool compare_cell_list_less_than(Layer * layer_b) const;





};

#endif /* LAYER_H_ */
